Skip to main content

Creating lock adapters

Implementing your custom ILockAdapter

In order to create an adapter you need to implement the ILockAdapter contract:

// filename: MyLockAdapter.ts
import type { ILockAdapter } from "@daiso-tech/core/lock/contracts";
import type { TimeSpan } from "@daiso-tech/core/utilities";

export class MyLockAdapter implements ILockAdapter {
acquire(
key: string,
owner: string,
ttl: TimeSpan | null,
): PromiseLike<boolean> {
throw new Error("Method not implemented.");
}

release(key: string, owner: string): PromiseLike<boolean> {
throw new Error("Method not implemented.");
}

forceRelease(key: string): PromiseLike<void> {
throw new Error("Method not implemented.");
}

refresh(key: string, owner: string, ttl: TimeSpan): PromiseLike<boolean> {
throw new Error("Method not implemented.");
}
}

The ILockAdapter contract uses PromiseLike instead of Promise to maintain compatibility with:

  • Native JavaScript Promises
  • Alternative promise libraries (e.g., Bluebird)
  • Any Promise/A+ compliant implementation

This provides flexibility while ensuring standard promise behavior is maintained.

Key benefits:

  • Works across different promise implementations (good for integrating legacy code)
  • Maintains type safety while being less restrictive
info

In order to use async function you need to replace PromiseLike with Promise:

// filename: MyLockAdapter.ts
import type { ILockAdapter } from "@daiso-tech/core/lock/contracts";
import type { TimeSpan } from "@daiso-tech/core/utilities";

export class MyLockAdapter implements ILockAdapter {
async acquire(
key: string,
owner: string,
ttl: TimeSpan | null,
): Promise<boolean> {
throw new Error("Method not implemented.");
}

async release(key: string, owner: string): Promise<boolean> {
throw new Error("Method not implemented.");
}

async forceRelease(key: string): Promise<void> {
throw new Error("Method not implemented.");
}

async refresh(key: string, owner: string, ttl: TimeSpan): Promise<boolean> {
throw new Error("Method not implemented.");
}
}

Testing your custom ILockAdapter

We provide a complete test suite to verify your event bus adapter implementation. Simply use the lockAdapterTestSuite function:

  • Preconfigured Vitest test cases
  • Standardized event bus behavior validation
  • Common edge case coverage

Usage example:

// filename: MyLockAdapter.test.ts

import { beforeEach, describe, expect, test } from "vitest";
import { lockAdapterTestSuite } from "@daiso-tech/core/lock/test-utilities";
import { MemoryLockAdapter } from "./MemoryLockAdapter.js";

describe("class: MyLockAdapter", () => {
lockAdapterTestSuite({
createAdapter: () => new MemoryLockAdapter(),
test,
beforeEach,
expect,
describe,
});
});

Implementing your custom IDatabaseLockAdapter

We provide an additional contract IDatabaseLockAdapter for building custom lock adapters tailored to databases:

// MyDatabaseLockAdapter.ts
import type {
ILockData,
IDatabaseLockAdapter,
} from "@daiso-tech/core/lock/contracts";

export class MyDatabaseLockAdapter implements IDatabaseLockAdapter {
insert(
key: string,
owner: string,
expiration: Date | null,
): PromiseLike<void> {
throw new Error("Method not implemented.");
}

update(
key: string,
owner: string,
expiration: Date | null,
): PromiseLike<number> {
throw new Error("Method not implemented.");
}

remove(key: string, owner: string | null): PromiseLike<void> {
throw new Error("Method not implemented.");
}

refresh(key: string, owner: string, expiration: Date): PromiseLike<number> {
throw new Error("Method not implemented.");
}

find(key: string): PromiseLike<ILockData | null> {
throw new Error("Method not implemented.");
}
}

The IDatabaseLockAdapter contract uses PromiseLike instead of Promise to maintain compatibility with:

  • Native JavaScript Promises
  • Alternative promise libraries (e.g., Bluebird)
  • Any Promise/A+ compliant implementation

This provides flexibility while ensuring standard promise behavior is maintained.

Key benefits:

  • Works across different promise implementations (good for integrating legacy code)
  • Maintains type safety while being less restrictive
info

In order to use async function you need to replace PromiseLike with Promise:

// MyDatabaseLockAdapter.ts
import type {
ILockData,
IDatabaseLockAdapter,
} from "@daiso-tech/core/lock/contracts";

export class MyDatabaseLockAdapter implements IDatabaseLockAdapter {
async insert(
key: string,
owner: string,
expiration: Date | null,
): Promise<void> {
throw new Error("Method not implemented.");
}

async update(
key: string,
owner: string,
expiration: Date | null,
): Promise<number> {
throw new Error("Method not implemented.");
}

async remove(key: string, owner: string | null): Promise<void> {
throw new Error("Method not implemented.");
}

async refresh(
key: string,
owner: string,
expiration: Date,
): Promise<number> {
throw new Error("Method not implemented.");
}

async find(key: string): Promise<ILockData | null> {
throw new Error("Method not implemented.");
}
}

Testing your custom IDatabaseLockAdapter

We provide a complete test suite to verify your event bus adapter implementation. Simply use the databaseLockAdapterTestSuite function:

  • Preconfigured Vitest test cases
  • Standardized event bus behavior validation
  • Common edge case coverage

Usage example:

import { beforeEach, describe, expect, test } from "vitest";
import { databaseLockAdapterTestSuite } from "@daiso-tech/core/lock/test-utilities";
import { MyDatabaseLockAdapter } from "./MyDatabaseLockAdapter.js";

describe("class: MyDatabaseLockAdapter", () => {
databaseLockAdapterTestSuite({
createAdapter: async () => {
return new MyDatabaseLockAdapter(),
},
test,
beforeEach,
expect,
describe,
});
});

Implementing your custom ILockProvider class

In some cases, you may need to implement a custom LockProvider class to optimize performance for your specific technology stack. You can then directly implement the ILockProvider contract.

Testing your custom ILockProvider class

We provide a complete test suite to verify your custom event bus class implementation. Simply use the lockProviderTestSuite function:

  • Preconfigured Vitest test cases
  • Standardized event bus behavior validation
  • Common edge case coverage

Usage example:

// filename: MyLockProvider.test.ts

import { beforeEach, describe, expect, test } from "vitest";
import { lockProviderTestSuite } from "@daiso-tech/core/lock/test-utilities";
import { MyLockProvider } from "./MyLockProvider.js";

describe("class: MyLockProvider", () => {
lockProviderTestSuite({
createLockProvider: () => new MyLockProvider(),
test,
beforeEach,
expect,
describe,
});
});